package com.classic.okhttp.crypt;


import com.classic.okhttp.defer.CoreDeferObject;
import com.classic.okhttp.defer.impl.DeferSecret;
import com.orhanobut.logger.Logger;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**
 * Created by rockey on 16/5/12.
 */
public class RSA implements DeferSecret {

    public RSA(){}

    private static String iv= "SHA256withRSA";

    private String publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbHYRGXPNNuA5w/8hRl5V45/GA\n" +
            "dqjB3hwor4vHGnBeUwdYOQMdtPDHDaYQqhKB0doDGhg2rNZK2UIEi7sUQYmfGNSc\n" +
            "H5BxtS67ZcKeqVjHvC6xoo85zoYA4bdGhy0MrYol9hexzxKj9ZihiQ826gqgUwV2\n" +
            "ihNSVjmp4kJ+PVhFjQIDAQAB";

    public void setPublicKey(String publicKey) {
        this.publicKey = publicKey;
    }

    public  PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes =  CoreDeferObject.get().getDeferBase64().base64Decode(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    private  String encrypt(String sSrc, RSAPublicKey sKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//"算法/模式/补码方式"
        cipher.init(Cipher.ENCRYPT_MODE, sKey);//,new IvParameterSpec(iv.getBytes())
        byte[] data= sSrc.getBytes("utf-8");
        int inputLen =data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > 117) {
                cache = cipher.doFinal(data, offSet, 117);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            System.out.println("length  "+cache.length);
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * 117;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return new String(CoreDeferObject.get().getDeferBase64().base64(encryptedData));
    }

    /**
     * @param content 原文
     * @param sign 签名
     * @param key
     * @return
     */
    private  boolean verify(String content,String sign,RSAPublicKey key)
    {
        try {
            Signature signature = Signature.getInstance(iv);
            signature.initVerify(key);
            signature.update("content".getBytes("utf-8"));
            return 	signature.verify(CoreDeferObject.get().getDeferBase64().base64Decode(sign));
        } catch (NoSuchAlgorithmException e) {
            Logger.e(e.getMessage());
            Logger.e(e.getMessage());
        } catch (InvalidKeyException e) {
            Logger.e(e.getMessage());
        } catch (SignatureException e) {
            Logger.e(e.getMessage());
        } catch (UnsupportedEncodingException e) {
            Logger.e(e.getMessage());
        }
        return false;
    }

    @Override
    public String encrypt(String content)  {
        try {
            return encrypt(content,(RSAPublicKey)getPublicKey(publicKey));
        } catch (Exception e) {
          Logger.e(e.getMessage());
        }
        return null;
    }

    /**
     *
     * @param content 原文
     * @param sign 签名
     */
    public boolean verify(String content,String sign)
    {
        try {
            return verify(content,sign,(RSAPublicKey)getPublicKey(publicKey));
        } catch (Exception e) {
            Logger.i(e.getCause().getMessage());
        }
        return false;
    }


    @Deprecated
    @Override
    public String decrypt(String content) throws Exception {
        return null;
    }
}
